package com.andon.microcellsimulator.http;

import android.app.Application;
import android.text.TextUtils;
import android.util.Log;

import com.alibaba.fastjson.JSON;
import com.andon.microcellsimulator.activity.DeviceListActivity;
import com.andon.microcellsimulator.common.util.JsonUtil;
import com.andon.microcellsimulator.common.util.RSAUtils;
import com.andon.microcellsimulator.http.response.BaseResponse;
import com.andon.microcellsimulator.http.response.IOTCommunicateStepBean1;
import com.andon.microcellsimulator.http.response.IOTCommunicateStepBean2;
import com.andon.microcellsimulator.http.response.IOTCommunicateStepBean3;
import com.andon.microcellsimulator.model.GlobalBean;
import com.andon.microcellsimulator.model.GlobalBeanManager;
import com.google.gson.Gson;
import com.lzy.okgo.OkGo;
import com.lzy.okgo.callback.StringCallback;
import com.lzy.okgo.https.HttpsUtils;
import com.lzy.okgo.interceptor.HttpLoggingInterceptor;
import com.lzy.okgo.model.HttpParams;
import com.lzy.okgo.model.Response;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;

import okhttp3.OkHttpClient;

/**
 * author: baiwenlong
 * created on: 2017/12/4 上午10:38
 * description: AP 与 IOT 通信相关接口封装
 */
public class IOTClient {


    private String RSA = "";//RSA KEY
    private String equipmentId = "";//设备ID
    private static final int VERSION = 1;

    private static class IOTClientHolder {
        private static final IOTClient INSTANCE = new IOTClient();
    }

    private IOTClient() {
    }

    public static final IOTClient getInstance() {
        return IOTClientHolder.INSTANCE;
    }

    /**
     * 网络接口结果回调
     */
    public interface NetWorkCallBack {

        void onSuccess(String json);

        void onError(String result);
    }

    /**
     * @param mRSA         RSA秘钥
     * @param mEquipmentId 设备ID
     */
    public void init(String mRSA, String mEquipmentId) {
        RSA = mRSA;
        equipmentId = mEquipmentId;
        if (TextUtils.isEmpty(mRSA)) {
            throw new IllegalStateException("RSA key不能为空。。。");
        }
        if (TextUtils.isEmpty(equipmentId)) {
            throw new IllegalStateException("设备ID不能为空。。。");
        }
    }

    /**
     * 初始化网络框架
     *
     * @param app 上下文环境
     */
    public void initOkGo(Application app) {
        OkHttpClient.Builder builder = new OkHttpClient.Builder();
        HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor("网络请求回调");
        //log打印级别，决定了log显示的详细程度
        loggingInterceptor.setPrintLevel(HttpLoggingInterceptor.Level.BODY);
        //log颜色级别，决定了log在控制台显示的颜色
        loggingInterceptor.setColorLevel(Level.INFO);
        builder.addInterceptor(loggingInterceptor);
        //全局的读取超时时间
        builder.readTimeout(25000, TimeUnit.MILLISECONDS);
        //全局的写入超时时间
        builder.writeTimeout(25000, TimeUnit.MILLISECONDS);
        //全局的连接超时时间
        builder.connectTimeout(25000, TimeUnit.MILLISECONDS);
        //设置Https信任所有证书,不安全有风险
        HttpsUtils.SSLParams params = HttpsUtils.getSslSocketFactory();
        builder.sslSocketFactory(params.sSLSocketFactory, params.trustManager);
        OkGo.getInstance().init(app)                       //必须调用初始化
                .setOkHttpClient(builder.build())               //必须设置OkHttpClient
                .setRetryCount(0);//全局统一超时重连次数，默认为三次，那么最差的情况会请求4次(一次原始请求，三次重连请求)，不需要可以设置为0
    }

    /**
     * AP设备与云端认证
     * @param netWorkCallBack
     */
    public void requestAPCommunicateToCloud(final NetWorkCallBack netWorkCallBack) {
        Map<String, String> paramsOne = new HashMap<>();
        paramsOne.put("did", equipmentId);
        OkGo.<String>post(IOTUrls.AUTH_S1)
                .upJson(new Gson().toJson(paramsOne))
                .execute(new StringCallback() {
                    @Override
                    public void onSuccess(Response<String> response) {
//                        Log.e("通讯第一步返回的结果Success", response.body() + "");
                        final IOTCommunicateStepBean1 iotCommunicateStepBean1 = JSON.parseObject(response.body(), IOTCommunicateStepBean1.class);
                        //第二步骤
                        HashMap<Object, Object> paramsTwo = new HashMap<>();
                        paramsTwo.put("did", equipmentId);
                        paramsTwo.put("ticket", iotCommunicateStepBean1.getReturnValue().getTicket());
                        paramsTwo.put("algo", iotCommunicateStepBean1.getReturnValue().getAlgos().get(0));
                        OkGo.<String>post(IOTUrls.AUTH_S2)
                                .upJson(new Gson().toJson(paramsTwo))
                                .execute(new StringCallback() {
                                    @Override
                                    public void onSuccess(Response<String> response) {
//                                        Log.e("通讯第二步返回的结果Success", response.body() + "");
                                        //第三步骤
                                        IOTCommunicateStepBean2 iotCommunicateStepBean2 = JSON.parseObject(response.body(), IOTCommunicateStepBean2.class);
                                        try {
                                            HashMap<Object, Object> paramsThree = new HashMap<>();
                                            String encryptByPrivateKey = RSAUtils.sign(iotCommunicateStepBean2.getReturnValue().getMsgDigest().getBytes(), RSA, "MD5");
                                            paramsThree.put("did", equipmentId);
                                            paramsThree.put("ticket", iotCommunicateStepBean1.getReturnValue().getTicket());
                                            paramsThree.put("signature", encryptByPrivateKey);
                                            OkGo.<String>post(IOTUrls.AUTH_S3)
                                                    .upJson(new Gson().toJson(paramsThree))
                                                    .execute(new StringCallback() {
                                                        @Override
                                                        public void onSuccess(Response<String> response) {

                                                            Log.e("通讯第三步返回的结果Success", response.body() + "");

                                                            IOTCommunicateStepBean3 jsonBean = JsonUtil.toObj(response.body(), IOTCommunicateStepBean3.class);

                                                            if (jsonBean != null && jsonBean.getReturnValue() != null) {
                                                                GlobalBean globalBean = GlobalBeanManager.getGlobalBean();

                                                                if (globalBean == null) {
                                                                    globalBean = new GlobalBean();
                                                                }

                                                                globalBean.setDeviceID(equipmentId);
                                                                globalBean.setRsa(RSA);
                                                                globalBean.setAccessToken(jsonBean.getReturnValue().getToken());
                                                                globalBean.setAccessExpire(jsonBean.getReturnValue().getExpireIn());

                                                                GlobalBeanManager.setGlobalBean(globalBean);

                                                                if (netWorkCallBack != null) {
                                                                    netWorkCallBack.onSuccess(response.body());
                                                                }
                                                            } else {
                                                                Log.e("通讯第三步返回的结果Success", "解析数据格式错误");
                                                            }

                                                        }
                                                        @Override
                                                        public void onError(Response<String> response) {
                                                            super.onError(response);
                                                            if (netWorkCallBack != null) {
                                                                netWorkCallBack.onError(response.body());
                                                            }
                                                            Log.e("Error", response.body() + "");
                                                        }
                                                    });
                                        } catch (Exception e) {
                                            e.printStackTrace();
                                        }
                                    }
                                    @Override
                                    public void onError(Response<String> response) {
                                        super.onError(response);
                                        if (netWorkCallBack != null) {
                                            netWorkCallBack.onError(response.body());
                                        }
                                        Log.e("Error", response.body() + "");
                                    }
                                });


                    }

                    @Override
                    public void onError(Response<String> response) {
                        super.onError(response);
                        if (netWorkCallBack != null) {
                            netWorkCallBack.onError(response.body());
                        }
                        Log.e("Error", response.body() + "");
                    }
                });
    }


    /**
     * 默认用户配置信息获取  返回
     *{"result":2,"msg":"SettingFile was null.","code":210,"returnValue":null,"ts":1512442920838}
     * 需要在后台配置
     */
    public void getDefaultUserSetting(String token, final NetWorkCallBack netWorkCallBack) {
        HashMap<Object, Object> map = new HashMap<>();
        map.put("did", equipmentId);
        map.put("token", token);
        map.put("ap", equipmentId);
        map.put("ver", VERSION);
        OkGo.<String>post(IOTUrls.DEFAULT_USER_SETTING)
                .upJson(new Gson().toJson(map))
                .execute(new StringCallback() {
                    @Override
                    public void onSuccess(Response<String> response) {
                        parseResponse(response, netWorkCallBack);
                    }

                    @Override
                    public void onError(Response<String> response) {
                        super.onError(response);
                        netWorkCallBack.onError(response.body());
                        Log.e("Error", response.body() + "");
                    }
                });

    }

    /**
     * 设备属性信息同步
     *
     * @param token
     * @param netWorkCallBack
     */
    public void propertiesSync(String token, String lanIP, final NetWorkCallBack netWorkCallBack) {
        HashMap<Object, Object> map = new HashMap<>();
        map.put("did", equipmentId);
        map.put("token", token);
        map.put("ap", equipmentId);
        map.put("lanIP", lanIP);
        OkGo.<String>post(IOTUrls.PROPERTIES_SYNC)
                .upJson(new Gson().toJson(map))
                .execute(new StringCallback() {
                    @Override
                    public void onSuccess(Response<String> response) {
                        netWorkCallBack.onSuccess(response.body());
                        Log.e("设备属性信息同步的结果Success", response.body() + "");
                    }

                    @Override
                    public void onError(Response<String> response) {
                        super.onError(response);
                        netWorkCallBack.onError(response.body());
                        Log.e("Error", response.body() + "");
                    }
                });

    }
    /**
     * CP设备接入
     * @param token
     * @param cps
     * @param netWorkCallBack
     */
    public void requestCPEquipmentJoin(String token, String[] cps, final NetWorkCallBack netWorkCallBack) {
        HashMap<Object, Object> map = new HashMap<>();
        map.put("did", equipmentId);
        map.put("token", token);
        map.put("cps", cps);
        map.put("ts", System.currentTimeMillis());
        OkGo.<String>post(IOTUrls.CP_JOIN)
                .upJson(new Gson().toJson(map))
                .execute(new StringCallback() {
                    @Override
                    public void onSuccess(Response<String> response) {
                        parseResponse(response, netWorkCallBack);
                    }
                    @Override
                    public void onError(Response<String> response) {
                        super.onError(response);
                        netWorkCallBack.onError(response.body());
                        Log.e("Error", response.body() + "");
                    }
                });

    }

    /**
     * CP设备脱离
     *
     * @param token
     * @param cps
     * @param netWorkCallBack
     */
    public void requestCPEquipmentDisJoin(String token, String[] cps, final NetWorkCallBack netWorkCallBack) {
        HashMap<Object, Object> map = new HashMap<>();
        map.put("did", equipmentId);
        map.put("token", token);
        map.put("cps", cps);
        map.put("ts", System.currentTimeMillis());
        OkGo.<String>post(IOTUrls.CP_DIS_JOIN)
                .upJson(new Gson().toJson(map))
                .execute(new StringCallback() {
                    @Override
                    public void onSuccess(Response<String> response) {
                        parseResponse(response, netWorkCallBack);
                    }

                    @Override
                    public void onError(Response<String> response) {
                        super.onError(response);
                        netWorkCallBack.onError(response.body());
                        Log.e("Error", response.body() + "");
                    }
                });

    }

    /**
     * 设备数据上报
     * @param did
     * @param token
     * @param data            设备数据
     * @param type            上报数据类型,可选
     * @param sid             消息ID,可选
     * @param netWorkCallBack
     */
    public void equipmentDataUpload(String did, String token, String data, String type, String sid, final NetWorkCallBack netWorkCallBack) {
        HashMap<Object, Object> map = new HashMap<>();
        map.put("did", did);
        map.put("token", token);
        map.put("ap", equipmentId);
        map.put("data", data);
        if (!TextUtils.isEmpty(type)) {
            map.put("type", type);
        }
        if (!TextUtils.isEmpty(sid)) {
            map.put("sid", sid);
        }
        map.put("ts", System.currentTimeMillis());
        OkGo.<String>post(IOTUrls.EQUIPMENT_UPLOAD_DATA)
                .upJson(new Gson().toJson(map))
                .execute(new StringCallback() {
                    @Override
                    public void onSuccess(Response<String> response) {
                        parseResponse(response, netWorkCallBack);
                    }

                    @Override
                    public void onError(Response<String> response) {
                        super.onError(response);
                        netWorkCallBack.onError(response.body());
                        Log.e("Error", response.body() + "");
                    }
                });

    }


    /**
     * AP获取组名单
     * @param token
     * @param netWorkCallBack
     */
    public void getGroupList(String token, final NetWorkCallBack netWorkCallBack) {
        HashMap<Object, Object> map = new HashMap<>();
        map.put("did", equipmentId);
        map.put("token", token);
        OkGo.<String>post(IOTUrls.GET_GROUP_LIST)
                .upJson(new Gson().toJson(map))
                .execute(new StringCallback() {
                    @Override
                    public void onSuccess(Response<String> response) {
                        parseResponse(response, netWorkCallBack);
                    }
                    @Override
                    public void onError(Response<String> response) {
                        super.onError(response);
                        netWorkCallBack.onError(response.body());
                        Log.e("Error", response.body() + "");
                    }
                });

    }

    /**
     * AP发起CP绑定
     * @param token
     * @param ap 实际的AP的设备id
     * @param netWorkCallBack
     */
    public void requestAPBindCP(String token,String ap,final NetWorkCallBack netWorkCallBack) {
        HashMap<Object, Object> map = new HashMap<>();
        map.put("did", equipmentId);
        map.put("token", token);
        map.put("ap", ap);
        OkGo.<String>post(IOTUrls.AP_BIND_CP)
                .upJson(new Gson().toJson(map))
                .execute(new StringCallback() {
                    @Override
                    public void onSuccess(Response<String> response) {
                        parseResponse(response, netWorkCallBack);
                    }
                    @Override
                    public void onError(Response<String> response) {
                        super.onError(response);
                        netWorkCallBack.onError(response.body());
                        Log.e("Error", response.body() + "");
                    }
                });

    }

    /**
     * AP发起CP解除绑定
     * @param token
     * @param ap 实际的AP的设备id
     * @param netWorkCallBack
     */
    public void requestAPUnBindCP(String token,String ap,final NetWorkCallBack netWorkCallBack) {
        HashMap<Object, Object> map = new HashMap<>();
        map.put("did", equipmentId);
        map.put("token", token);
        map.put("ap", ap);
        OkGo.<String>post(IOTUrls.AP_UNBIND_CP)
                .upJson(new Gson().toJson(map))
                .execute(new StringCallback() {
                    @Override
                    public void onSuccess(Response<String> response) {
                        parseResponse(response, netWorkCallBack);
                    }
                    @Override
                    public void onError(Response<String> response) {
                        super.onError(response);
                        netWorkCallBack.onError(response.body());
                        Log.e("Error", response.body() + "");
                    }
                });
    }

    public void parseResponse(Response<String> response, NetWorkCallBack netWorkCallBack) {
        // 判断HTTP协议状态码
        if (response.code() == 200) {
            BaseResponse baseResponse = JsonUtil.toObj(response.body(), BaseResponse.class);
            if (baseResponse != null) {
                if (baseResponse.getCode() == 100) {
                    // 正常返回
                    netWorkCallBack.onSuccess(response.body());
                } else if (baseResponse.getCode() == 203) {
                    // Token错误或过期
                    requestAPCommunicateToCloud(null);
                    netWorkCallBack.onError(response.body());
                    Log.e("TokenError", response.body() + "");

                } else {
                    netWorkCallBack.onError(response.body());
                    Log.e("LogicError", response.body() + "");

                }
            } else {
                netWorkCallBack.onError(response.body());
                Log.e("JsonError", response.body() + "");
            }
        } else {
            netWorkCallBack.onError(response.body());
            Log.e("LogicError", response.body() + "");
        }
    }

    //------------------RDS服务------------------

    /**
     * 获取服务地址
     * @param names 服务端给客户端的命名，至少要输入一个，可以是多个，用英文“,”间隔，用以一次查询多个地址
     * @param ip 上报客户端IP
     */
    public void getRDSProtocol(String names, String ip, final NetWorkCallBack netWorkCallBack){
        HttpParams params  = new HttpParams();
        params.put("names", names);
        params.put("ip", ip);
        OkGo.<String>get(IOTUrls.GET_RDS)
                .params(params)
                .execute(new StringCallback() {
                    @Override
                    public void onSuccess(Response<String> response) {
                        netWorkCallBack.onSuccess(response.body());
                        Log.e("获取服务地址的结果Success", response.body() + "");
                    }
                    @Override
                    public void onError(Response<String> response) {
                        super.onError(response);
                        netWorkCallBack.onError(response.body());
                        Log.e("Error", response.body() + "");
                    }
                });
    }



}
